package com.ruoyi.apijson.config;

import java.util.List;

import org.springframework.data.redis.core.StringRedisTemplate;

import com.github.pagehelper.PageHelper;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
import com.ruoyi.generator.service.GenTableColumnServiceImpl;
import com.ruoyi.generator.service.GenTableServiceImpl;

import apijson.JSONObject;
import apijson.framework.APIJSONApplication;
import apijson.framework.APIJSONFunctionParser;
import apijson.framework.APIJSONVerifier;
import apijson.orm.AbstractVerifier;
import apijson.router.APIJSONRouterApplication;
import apijson.router.APIJSONRouterVerifier;

public class ApijsonInitUtil {
	public static boolean IS_INIT_SHUTDOWNWHENSERVERERROR = false;
	public static final String REDIS_TABLE_CONFIG_HASH_KEY = "apijson:table:key:config";
	public static final String REDIS_TABLE_KEY_PK = "pk";
	public static final String REDIS_TABLE_KEY_PK_INCREMENT = "increment";
	public static final String REDIS_TABLE_KEY_USERID = "userId";
	
	/***
	 * 全量初始化
	 * 
	 * @throws Exception
	 */
	public static void init() throws Exception {
		// 默认只会初始化 100条数据
		APIJSONApplication.init(IS_INIT_SHUTDOWNWHENSERVERERROR); // 4.4.0 以上需要这句来保证以上 static 代码块中给
																	// DEFAULT_APIJSON_CREATOR 赋值会生效
		// 需要将超过100条的记录进行增量初始化
		// 通过总条数判断是否已经加载完成
		initAccess();
		initFunction();
		initRequest();
		initTableKeyMap();

		APIJSONRouterApplication.init();
		initDocument();

		// 初始化 表-主键， 表-创建人对照关系
		initConfigTableUserId();
	}
	
	
	public static void initConfigTableUserId(String tableName, String userId, List<GenTableColumn> genTableColumns) {
		String pk = null;
		for(GenTableColumn column : genTableColumns) {
			if(column.isPk()) {
				setTablePk(tableName, column.getColumnName());
				pk = column.getColumnName();
				if(column.isIncrement()) {
					setTablePkIncrement(tableName, column.getColumnName());
				}
			}
		}
		
		// 不存在UserId，将id 和 UserId填写为一样
		if(userId == null) {
			setTableUserIdById(tableName, pk);
		} else {
			setTableUserId(tableName, userId);
		}
	}

	/***
	 * 初始化 表-主键， 表-创建人对照关系
	 */
	public static void initConfigTableUserId() {
		GenTableServiceImpl genTableService = SpringUtils.getBean("genTableServiceImpl", GenTableServiceImpl.class);
		GenTableColumnServiceImpl genTableColumnService = SpringUtils.getBean("genTableColumnServiceImpl", GenTableColumnServiceImpl.class);
		
		int pageNum = 1;
		while (true) {
			PageHelper.startPage(pageNum, 50, "table_id");
			GenTable genTableSearch = new GenTable();
			List<GenTable> list = genTableService.selectGenTableList(genTableSearch);
			if (list.size() == 0) {
				break;
			}
			for (GenTable genTable : list) {
				// 查询表字段
				List<GenTableColumn> listColumn = genTableColumnService.selectGenTableColumnListByTableId(genTable.getTableId());
				initConfigTableUserId(genTable.getTableName(), genTableSearch.getUserId() , listColumn);
			}
			pageNum++;
		}
	}
	
	public static void deleteTablePkConfig(String tableName) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		stringRedisTemplate.delete(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase());
	}	
	
	public static void setTablePkIncrement(String tableName, String columnName) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		stringRedisTemplate.opsForHash().put(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase(), REDIS_TABLE_KEY_PK_INCREMENT, "1");
	}
	
	public static void setTablePk(String tableName, String columnName) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		stringRedisTemplate.opsForHash().put(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase(), REDIS_TABLE_KEY_PK, columnName);
	}
	
	public static void setTableUserId(String tableName, String userId) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		stringRedisTemplate.opsForHash().put(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase(), REDIS_TABLE_KEY_USERID, userId);
	}
	
	/***
	 * 不存在UserId， 设置为主键
	 * @param tableName
	 * @param columnName
	 * @param columnComment
	 */
	public static void setTableUserIdById(String tableName, String pk) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		stringRedisTemplate.opsForHash().put(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase(), REDIS_TABLE_KEY_USERID, pk);
	}
	
	public static Object getTablePkIncrement(String tableName) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		return stringRedisTemplate.opsForHash().get(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase(), REDIS_TABLE_KEY_PK_INCREMENT);
	}
	
	public static Object getTablePk(String tableName) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		Object pk = stringRedisTemplate.opsForHash().get(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase(), REDIS_TABLE_KEY_PK);
		return pk;
	}
	
	public static Object getTableUserId(String tableName) {
		StringRedisTemplate stringRedisTemplate = SpringUtils.getBean("stringRedisTemplate", StringRedisTemplate.class);
		return stringRedisTemplate.opsForHash().get(REDIS_TABLE_CONFIG_HASH_KEY+":"+tableName.toLowerCase(), REDIS_TABLE_KEY_USERID);
	}
	

	public static void initTableKeyMap() {
		// 表名映射，隐藏真实表名，对安全要求很高的表可以这么做
		// APIJSONSQLConfig.TABLE_KEY_MAP.put("ES_blog", "es_blog");
		// APIJSONSQLConfig.TABLE_KEY_MAP.put("Sys_oper_log_local", "Sys_oper_log");
	}

	private static void initAccess() throws Exception {
		int accessMapCount = AbstractVerifier.ACCESS_MAP.size();
		int eveNum = 1;
		while (true) {
			JSONObject table = new JSONObject();
			table.put("id{}", ">=" + (100 * eveNum));
			table.setOrder("id+");
			APIJSONVerifier.initAccess(IS_INIT_SHUTDOWNWHENSERVERERROR, APIJSONApplication.DEFAULT_APIJSON_CREATOR,
					table);
			int tmp_accessMapCount = AbstractVerifier.ACCESS_MAP.size();
			if (accessMapCount == tmp_accessMapCount) {
				break;
			} else {
				accessMapCount = tmp_accessMapCount;
			}
			eveNum++;
		}
	}

	private static void initFunction() throws Exception {
		int accessMapCount = APIJSONFunctionParser.FUNCTION_MAP.size();
		int eveNum = 1;
		while (true) {
			JSONObject table = new JSONObject();
			table.put("id{}", ">=" + (30 * eveNum));
			table.setOrder("id+");
			APIJSONFunctionParser.init(IS_INIT_SHUTDOWNWHENSERVERERROR, APIJSONApplication.DEFAULT_APIJSON_CREATOR,
					table);
			int tmp_accessMapCount = APIJSONFunctionParser.FUNCTION_MAP.size();
			if (accessMapCount == tmp_accessMapCount) {
				break;
			} else {
				accessMapCount = tmp_accessMapCount;
			}
			eveNum++;
		}
	}

	public static void initDocument() throws Exception {
		int documentMapCount = APIJSONRouterVerifier.DOCUMENT_MAP.size();
		int eveNum = 1;
		while (true) {
			JSONObject table = new JSONObject();
			table.put("id{}", ">=" + (100 * eveNum));
			table.setOrder("id+");
			APIJSONRouterVerifier.initDocument(IS_INIT_SHUTDOWNWHENSERVERERROR,
					APIJSONApplication.DEFAULT_APIJSON_CREATOR, table);
			int tmp_accessMapCount = APIJSONRouterVerifier.DOCUMENT_MAP.size();
			if (documentMapCount == tmp_accessMapCount) {
				break;
			} else {
				documentMapCount = tmp_accessMapCount;
			}
			eveNum++;
		}
	}

	private static void initRequest() throws Exception {
		int accessMapCount = APIJSONVerifier.REQUEST_MAP.size();
		int eveNum = 1;
		while (true) {
			JSONObject table = new JSONObject();
			table.put("id{}", ">=" + (100 * eveNum));
			table.setOrder("version-,id+");
			APIJSONVerifier.initRequest(IS_INIT_SHUTDOWNWHENSERVERERROR, APIJSONApplication.DEFAULT_APIJSON_CREATOR,
					table);
			int tmp_accessMapCount = APIJSONVerifier.REQUEST_MAP.size();
			if (accessMapCount == tmp_accessMapCount) {
				break;
			} else {
				accessMapCount = tmp_accessMapCount;
			}
			eveNum++;
		}
	}

	public static void addInitAccess(Long id) throws Exception {
		JSONObject table = new JSONObject();
		table.put("id", id);
		table.setOrder("id+");
		APIJSONVerifier.initAccess(IS_INIT_SHUTDOWNWHENSERVERERROR, APIJSONApplication.DEFAULT_APIJSON_CREATOR, table);
		initTableKeyMap();
	}

	public static void addInitRequest(Long id) throws Exception {
		JSONObject table = new JSONObject();
		table.put("id", id);
		table.setOrder("version-,id+");
		APIJSONVerifier.initRequest(IS_INIT_SHUTDOWNWHENSERVERERROR, APIJSONApplication.DEFAULT_APIJSON_CREATOR, table);
		initTableKeyMap();
	}

	public static void addInitDocument(Long id) throws Exception {
		JSONObject table = new JSONObject();
		table.put("id", id);
		table.setOrder("version-,id+");
		APIJSONRouterVerifier.initDocument(IS_INIT_SHUTDOWNWHENSERVERERROR, APIJSONApplication.DEFAULT_APIJSON_CREATOR,
				table);
		initTableKeyMap();
	}

	public static void addInitFunction(Long id) throws Exception {
		JSONObject table = new JSONObject();
		table.put("id", id);
		table.setOrder("version-,id+");
		APIJSONFunctionParser.init(IS_INIT_SHUTDOWNWHENSERVERERROR, APIJSONApplication.DEFAULT_APIJSON_CREATOR, table);
		initTableKeyMap();
	}
}
